#include "Util.hpp"
#include "HttpServer.hpp"
#include <memory>
#include <vector>

const std::string SEP = "\r\n";
const std::string webRoot = "./wwwroot"; // web根目录
// 用户默认访问 / ，绝不能把整站发给对方，要有默认首页。
const std::string defaultHomePage = "index.html";
const std::string page_404 = "./wwwroot/err_404.html";

// 协议
class HttpRequest
{
public:
    HttpRequest()
        : _path(webRoot)
    {
    }
    ~HttpRequest() {}

    void Print()
    {
        logMessage(Info, "Method: %s, url: %s, version: %s",
                   _method.c_str(), _url.c_str(), _httpversion.c_str());

        for (const auto &line : _header)
            logMessage(Info, "%s", line.c_str());

        logMessage(Info, "Path: %s", _path.c_str());
    }

public:
    std::string _method;
    std::string _url;
    std::string _httpversion;
    std::vector<std::string> _header;
    std::string _path;
    std::string _suffix;
};

// 反序列化 http request
HttpRequest Deserialize(std::string &message)
{
    HttpRequest req;

    // 获取Request的_method, _url, _httpversion
    std::string line = Util::ReadOneLine(message, SEP);
    Util::ParseRequestLine(line, &req._method, &req._url, &req._httpversion);

    // 获取Request的_header
    while (!message.empty())
    {
        line = Util::ReadOneLine(message, SEP);
        req._header.push_back(line);
    }

    req._path += req._url;

    // 如果是目录，拼上默认首页
    if (req._path[req._path.size() - 1] == '/')
        req._path += defaultHomePage;

    auto pos = req._path.rfind(".");
    if (pos == std::string::npos)
        req._suffix = ".html";
    else
        req._suffix = req._path.substr(pos);

    return req;
}

std::string GetContentType(const std::string &suffix)
{
    std::string content_type = "Content-Type: ";
    if (suffix == ".html" || suffix == ".htm")
        content_type += "text/html";
    else if (suffix == ".css")
        content_type += "text/css";
    else if (suffix == ".js")
        content_type += "application/x-javascript";
    else if (suffix == ".png")
        content_type += "image/png";
    else if (suffix == ".jpg")
        content_type += "image/jpge";

    return content_type;
}

std::string HandlerHttp(std::string &message)
{
    // 1.读取请求并反序列化
    std::cout << "-------------------------------------------------------------------\n";
    HttpRequest req = Deserialize(message);
    req.Print();

    // 2.构建响应
    std::string body;
    std::string response;
    if (Util::ReadFile(req._path, &body))
    {
        response = "HTTP/1.0 200 OK" + SEP;
        response += "Content-Length: " + std::to_string(body.size()) + SEP;
        // 搜“Content-Type对照表”
        // response += "Content-Type: text/html" + SEP; // 这次我们加了类型，postman就知道响应的是html了，直接就给我们格式化了
        response += GetContentType(req._suffix) + SEP;
        response += SEP;
        response += body;
    }
    else
    {
        response = "HTTP/1.0 404 Not Found" + SEP;
        Util::ReadFile(page_404, &body);
        response += "Content-Length: " + std::to_string(body.size()) + SEP;
        response += GetContentType(".html") + SEP;
        response += SEP;
        response += body;
    }

    // 重定向状态测试
    // std::string response;
    // // response += "HTTP/1.0 302 Found" + SEP;
    // response += "HTTP/1.0 301 Moved Permanently" + SEP;
    // response += "Location: https://www.baidu.com/" + SEP;
    // response += SEP;

    // cookie session 测试
    //  std::string response;
    // response += "HTTP/1.0 200 OK" + SEP;
    // response += "Set-Cookie: sessionid=12345567" + SEP;
    // response += SEP;

    return response;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        std::cout << "./httpserver port\n";
        exit(USAGE_ERR);
    }

    uint16_t port = atoi(argv[1]);

    std::cout << "Hello, Httpserver\n";
    std::unique_ptr<HttpServer> pts(new HttpServer(HandlerHttp, port));

    pts->InitServer();
    pts->Start();

    return 0;
}
